package cn.com.transfer.services;

import cn.com.transfer.params.IcbcParams;
import cn.com.transfer.utils.Constants;
import cn.com.transfer.utils.IcbcInfo;
import org.apache.commons.lang.StringUtils;
import org.nutz.dao.Chain;
import org.nutz.dao.Cnd;
import org.nutz.dao.entity.Record;
import org.nutz.dao.impl.NutDao;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.net.Socket;
import java.util.Calendar;
import java.util.Map;

import static cn.com.transfer.utils.IcbcInfo.ip;
import static cn.com.transfer.utils.IcbcInfo.port;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;

/**
 * Created by Administrator on 2015/4/3.
 */
public abstract class MsgHandlerService {
    private Logger logger = LoggerFactory.getLogger(MsgHandlerService.class);
    public NutDao dao;

    public abstract String handler(Map params);

    public void checkCustomer(Record customer) {
        checkNotNull(customer, "用户数据不存在");
        checkArgument(customer.getInt("AccStat") == 0, "账号已停用");
        checkArgument(customer.getInt("CardStat") == 0, "卡已挂失,请先解挂");
        checkArgument(StringUtils.isNotBlank(customer.getString("id")), "请绑定身份证信息");
        checkArgument(StringUtils.isNotBlank(customer.getString("bankAccNo").replace(" ", "")), "请绑定银行卡");
    }

    public IcbcParams sendMessage(IcbcParams req) {
        IcbcParams resp = null;
        try {
            String respStr = null;
            for (int i = 0; i < 3; i++) {
                respStr = sendToBank(req.toString());
                if (respStr != null) break;
            }
            logger.info("reqStr=" + req.toString());
            logger.info("respStr=" + respStr);
            if (StringUtils.isNotBlank(respStr)) {
                resp = new IcbcParams(respStr);
                //验证mac
                /*String mac;
                if (resp.transCode.equals(Constants.ICBC_TRANS_SIGN_IN) || resp.transCode.equals(Constants.ICBC_TRANS_SIGN_BALANCE)) {
                    mac = resp.genMac(0);
                } else {
                    mac = resp.genMac(1);
                }
                checkArgument(mac.equalsIgnoreCase(resp.mac), "Mac验证失败");*/
            }
            return resp;
        } catch (Exception e) {
            logger.error("error in sendMessage", e);
            return null;
        }
    }

    private String sendToBank(String reqStr) {
        Socket socket = null;
        InputStream is = null;
        OutputStream os = null;
        try {
            logger.debug("ip : {}, port : {}", ip, port);
            socket = new Socket(ip, port);
            socket.setSoTimeout(1000 * 180);
            is = socket.getInputStream();
            os = socket.getOutputStream();
            os.write((String.format("%04d", reqStr.length()) + reqStr).getBytes());
            os.flush();

            byte[] len = new byte[4];
            if (is.read(len) != -1) {
                byte[] bytes = new byte[Integer.valueOf(new String(len))];
                is.read(bytes);
                return new String(bytes);
            }
        } catch (Exception e) {
            logger.error("error in method sendMessage", e);
        } finally {
            try {
                socket.close();
            } catch (Exception e) {
            }
            try {
                is.close();
            } catch (Exception e) {
            }
            try {
                os.close();
            } catch (Exception e) {
            }
        }
        return null;
    }

    public synchronized String getTransNo() {
        Calendar ca = Calendar.getInstance();
        StringBuffer transNo = new StringBuffer(String.format("%04d%02d%02d", ca.get(Calendar.YEAR), ca.get(Calendar.MONTH) + 1, ca.get(Calendar.DAY_OF_MONTH)).substring(2, 8));

        String type = "transNo";
        String no;
        Record para = dao.fetch("tb_syspara", Cnd.where("typeX", "=", type));
        if (para == null) {
            no = "000001";
            dao.insert("tb_syspara", Chain.make("typeX", type).add("valueX", no).add("note", "工行圈存流水序列"));
            transNo.append(no);
        } else {
            no = para.getString("valueX");
            no = String.format("%06d", Integer.valueOf(no) + 1);
            if (no.length() > 6) no = "000001";
            dao.update("tb_syspara", Chain.make("valueX", no), Cnd.where("typeX", "=", type));
            transNo.append(no);
        }
        return transNo.toString();
    }
}

